home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / test / test_minidom.py < prev    next >
Text File  |  2005-10-18  |  48KB  |  1,378 lines

  1. # test for xml.dom.minidom
  2.  
  3. import os
  4. import sys
  5. import pickle
  6. import traceback
  7. from StringIO import StringIO
  8. from test.test_support import verbose
  9.  
  10. import xml.dom
  11. import xml.dom.minidom
  12. import xml.parsers.expat
  13.  
  14. from xml.dom.minidom import parse, Node, Document, parseString
  15. from xml.dom.minidom import getDOMImplementation
  16.  
  17.  
  18. if __name__ == "__main__":
  19.     base = sys.argv[0]
  20. else:
  21.     base = __file__
  22. tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
  23. del base
  24.  
  25. def confirm(test, testname = "Test"):
  26.     if not test:
  27.         print "Failed " + testname
  28.         raise Exception
  29.  
  30. def testParseFromFile():
  31.     dom = parse(StringIO(open(tstfile).read()))
  32.     dom.unlink()
  33.     confirm(isinstance(dom,Document))
  34.  
  35. def testGetElementsByTagName():
  36.     dom = parse(tstfile)
  37.     confirm(dom.getElementsByTagName("LI") == \
  38.             dom.documentElement.getElementsByTagName("LI"))
  39.     dom.unlink()
  40.  
  41. def testInsertBefore():
  42.     dom = parseString("<doc><foo/></doc>")
  43.     root = dom.documentElement
  44.     elem = root.childNodes[0]
  45.     nelem = dom.createElement("element")
  46.     root.insertBefore(nelem, elem)
  47.     confirm(len(root.childNodes) == 2
  48.             and root.childNodes.length == 2
  49.             and root.childNodes[0] is nelem
  50.             and root.childNodes.item(0) is nelem
  51.             and root.childNodes[1] is elem
  52.             and root.childNodes.item(1) is elem
  53.             and root.firstChild is nelem
  54.             and root.lastChild is elem
  55.             and root.toxml() == "<doc><element/><foo/></doc>"
  56.             , "testInsertBefore -- node properly placed in tree")
  57.     nelem = dom.createElement("element")
  58.     root.insertBefore(nelem, None)
  59.     confirm(len(root.childNodes) == 3
  60.             and root.childNodes.length == 3
  61.             and root.childNodes[1] is elem
  62.             and root.childNodes.item(1) is elem
  63.             and root.childNodes[2] is nelem
  64.             and root.childNodes.item(2) is nelem
  65.             and root.lastChild is nelem
  66.             and nelem.previousSibling is elem
  67.             and root.toxml() == "<doc><element/><foo/><element/></doc>"
  68.             , "testInsertBefore -- node properly placed in tree")
  69.     nelem2 = dom.createElement("bar")
  70.     root.insertBefore(nelem2, nelem)
  71.     confirm(len(root.childNodes) == 4
  72.             and root.childNodes.length == 4
  73.             and root.childNodes[2] is nelem2
  74.             and root.childNodes.item(2) is nelem2
  75.             and root.childNodes[3] is nelem
  76.             and root.childNodes.item(3) is nelem
  77.             and nelem2.nextSibling is nelem
  78.             and nelem.previousSibling is nelem2
  79.             and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
  80.             , "testInsertBefore -- node properly placed in tree")
  81.     dom.unlink()
  82.  
  83. def _create_fragment_test_nodes():
  84.     dom = parseString("<doc/>")
  85.     orig = dom.createTextNode("original")
  86.     c1 = dom.createTextNode("foo")
  87.     c2 = dom.createTextNode("bar")
  88.     c3 = dom.createTextNode("bat")
  89.     dom.documentElement.appendChild(orig)
  90.     frag = dom.createDocumentFragment()
  91.     frag.appendChild(c1)
  92.     frag.appendChild(c2)
  93.     frag.appendChild(c3)
  94.     return dom, orig, c1, c2, c3, frag
  95.  
  96. def testInsertBeforeFragment():
  97.     dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
  98.     dom.documentElement.insertBefore(frag, None)
  99.     confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
  100.             "insertBefore(<fragment>, None)")
  101.     frag.unlink()
  102.     dom.unlink()
  103.     #
  104.     dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
  105.     dom.documentElement.insertBefore(frag, orig)
  106.     confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
  107.             "insertBefore(<fragment>, orig)")
  108.     frag.unlink()
  109.     dom.unlink()
  110.  
  111. def testAppendChild():
  112.     dom = parse(tstfile)
  113.     dom.documentElement.appendChild(dom.createComment(u"Hello"))
  114.     confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
  115.     confirm(dom.documentElement.childNodes[-1].data == "Hello")
  116.     dom.unlink()
  117.  
  118. def testAppendChildFragment():
  119.     dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
  120.     dom.documentElement.appendChild(frag)
  121.     confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
  122.             "appendChild(<fragment>)")
  123.     frag.unlink()
  124.     dom.unlink()
  125.  
  126. def testReplaceChildFragment():
  127.     dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
  128.     dom.documentElement.replaceChild(frag, orig)
  129.     orig.unlink()
  130.     confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
  131.             "replaceChild(<fragment>)")
  132.     frag.unlink()
  133.     dom.unlink()
  134.  
  135. def testLegalChildren():
  136.     dom = Document()
  137.     elem = dom.createElement('element')
  138.     text = dom.createTextNode('text')
  139.  
  140.     try: dom.appendChild(text)
  141.     except xml.dom.HierarchyRequestErr: pass
  142.     else:
  143.         print "dom.appendChild didn't raise HierarchyRequestErr"
  144.  
  145.     dom.appendChild(elem)
  146.     try: dom.insertBefore(text, elem)
  147.     except xml.dom.HierarchyRequestErr: pass
  148.     else:
  149.         print "dom.appendChild didn't raise HierarchyRequestErr"
  150.  
  151.     try: dom.replaceChild(text, elem)
  152.     except xml.dom.HierarchyRequestErr: pass
  153.     else:
  154.         print "dom.appendChild didn't raise HierarchyRequestErr"
  155.  
  156.     nodemap = elem.attributes
  157.     try: nodemap.setNamedItem(text)
  158.     except xml.dom.HierarchyRequestErr: pass
  159.     else:
  160.         print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
  161.  
  162.     try: nodemap.setNamedItemNS(text)
  163.     except xml.dom.HierarchyRequestErr: pass
  164.     else:
  165.         print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
  166.  
  167.     elem.appendChild(text)
  168.     dom.unlink()
  169.  
  170. def testNamedNodeMapSetItem():
  171.     dom = Document()
  172.     elem = dom.createElement('element')
  173.     attrs = elem.attributes
  174.     attrs["foo"] = "bar"
  175.     a = attrs.item(0)
  176.     confirm(a.ownerDocument is dom,
  177.             "NamedNodeMap.__setitem__() sets ownerDocument")
  178.     confirm(a.ownerElement is elem,
  179.             "NamedNodeMap.__setitem__() sets ownerElement")
  180.     confirm(a.value == "bar",
  181.             "NamedNodeMap.__setitem__() sets value")
  182.     confirm(a.nodeValue == "bar",
  183.             "NamedNodeMap.__setitem__() sets nodeValue")
  184.     elem.unlink()
  185.     dom.unlink()
  186.  
  187. def testNonZero():
  188.     dom = parse(tstfile)
  189.     confirm(dom)# should not be zero
  190.     dom.appendChild(dom.createComment("foo"))
  191.     confirm(not dom.childNodes[-1].childNodes)
  192.     dom.unlink()
  193.  
  194. def testUnlink():
  195.     dom = parse(tstfile)
  196.     dom.unlink()
  197.  
  198. def testElement():
  199.     dom = Document()
  200.     dom.appendChild(dom.createElement("abc"))
  201.     confirm(dom.documentElement)
  202.     dom.unlink()
  203.  
  204. def testAAA():
  205.     dom = parseString("<abc/>")
  206.     el = dom.documentElement
  207.     el.setAttribute("spam", "jam2")
  208.     confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
  209.     a = el.getAttributeNode("spam")
  210.     confirm(a.ownerDocument is dom,
  211.             "setAttribute() sets ownerDocument")
  212.     confirm(a.ownerElement is dom.documentElement,
  213.             "setAttribute() sets ownerElement")
  214.     dom.unlink()
  215.  
  216. def testAAB():
  217.     dom = parseString("<abc/>")
  218.     el = dom.documentElement
  219.     el.setAttribute("spam", "jam")
  220.     el.setAttribute("spam", "jam2")
  221.     confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
  222.     dom.unlink()
  223.  
  224. def testAddAttr():
  225.     dom = Document()
  226.     child = dom.appendChild(dom.createElement("abc"))
  227.  
  228.     child.setAttribute("def", "ghi")
  229.     confirm(child.getAttribute("def") == "ghi")
  230.     confirm(child.attributes["def"].value == "ghi")
  231.  
  232.     child.setAttribute("jkl", "mno")
  233.     confirm(child.getAttribute("jkl") == "mno")
  234.     confirm(child.attributes["jkl"].value == "mno")
  235.  
  236.     confirm(len(child.attributes) == 2)
  237.  
  238.     child.setAttribute("def", "newval")
  239.     confirm(child.getAttribute("def") == "newval")
  240.     confirm(child.attributes["def"].value == "newval")
  241.  
  242.     confirm(len(child.attributes) == 2)
  243.     dom.unlink()
  244.  
  245. def testDeleteAttr():
  246.     dom = Document()
  247.     child = dom.appendChild(dom.createElement("abc"))
  248.  
  249.     confirm(len(child.attributes) == 0)
  250.     child.setAttribute("def", "ghi")
  251.     confirm(len(child.attributes) == 1)
  252.     del child.attributes["def"]
  253.     confirm(len(child.attributes) == 0)
  254.     dom.unlink()
  255.  
  256. def testRemoveAttr():
  257.     dom = Document()
  258.     child = dom.appendChild(dom.createElement("abc"))
  259.  
  260.     child.setAttribute("def", "ghi")
  261.     confirm(len(child.attributes) == 1)
  262.     child.removeAttribute("def")
  263.     confirm(len(child.attributes) == 0)
  264.  
  265.     dom.unlink()
  266.  
  267. def testRemoveAttrNS():
  268.     dom = Document()
  269.     child = dom.appendChild(
  270.             dom.createElementNS("http://www.python.org", "python:abc"))
  271.     child.setAttributeNS("http://www.w3.org", "xmlns:python",
  272.                                             "http://www.python.org")
  273.     child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
  274.     confirm(len(child.attributes) == 2)
  275.     child.removeAttributeNS("http://www.python.org", "abcattr")
  276.     confirm(len(child.attributes) == 1)
  277.  
  278.     dom.unlink()
  279.  
  280. def testRemoveAttributeNode():
  281.     dom = Document()
  282.     child = dom.appendChild(dom.createElement("foo"))
  283.     child.setAttribute("spam", "jam")
  284.     confirm(len(child.attributes) == 1)
  285.     node = child.getAttributeNode("spam")
  286.     child.removeAttributeNode(node)
  287.     confirm(len(child.attributes) == 0
  288.             and child.getAttributeNode("spam") is None)
  289.  
  290.     dom.unlink()
  291.  
  292. def testChangeAttr():
  293.     dom = parseString("<abc/>")
  294.     el = dom.documentElement
  295.     el.setAttribute("spam", "jam")
  296.     confirm(len(el.attributes) == 1)
  297.     el.setAttribute("spam", "bam")
  298.     # Set this attribute to be an ID and make sure that doesn't change
  299.     # when changing the value:
  300.     el.setIdAttribute("spam")
  301.     confirm(len(el.attributes) == 1
  302.             and el.attributes["spam"].value == "bam"
  303.             and el.attributes["spam"].nodeValue == "bam"
  304.             and el.getAttribute("spam") == "bam"
  305.             and el.getAttributeNode("spam").isId)
  306.     el.attributes["spam"] = "ham"
  307.     confirm(len(el.attributes) == 1
  308.             and el.attributes["spam"].value == "ham"
  309.             and el.attributes["spam"].nodeValue == "ham"
  310.             and el.getAttribute("spam") == "ham"
  311.             and el.attributes["spam"].isId)
  312.     el.setAttribute("spam2", "bam")
  313.     confirm(len(el.attributes) == 2
  314.             and el.attributes["spam"].value == "ham"
  315.             and el.attributes["spam"].nodeValue == "ham"
  316.             and el.getAttribute("spam") == "ham"
  317.             and el.attributes["spam2"].value == "bam"
  318.             and el.attributes["spam2"].nodeValue == "bam"
  319.             and el.getAttribute("spam2") == "bam")
  320.     el.attributes["spam2"] = "bam2"
  321.     confirm(len(el.attributes) == 2
  322.             and el.attributes["spam"].value == "ham"
  323.             and el.attributes["spam"].nodeValue == "ham"
  324.             and el.getAttribute("spam") == "ham"
  325.             and el.attributes["spam2"].value == "bam2"
  326.             and el.attributes["spam2"].nodeValue == "bam2"
  327.             and el.getAttribute("spam2") == "bam2")
  328.     dom.unlink()
  329.  
  330. def testGetAttrList():
  331.     pass
  332.  
  333. def testGetAttrValues(): pass
  334.  
  335. def testGetAttrLength(): pass
  336.  
  337. def testGetAttribute(): pass
  338.  
  339. def testGetAttributeNS(): pass
  340.  
  341. def testGetAttributeNode(): pass
  342.  
  343. def testGetElementsByTagNameNS():
  344.     d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
  345.     <minidom:myelem/>
  346.     </foo>"""
  347.     dom = parseString(d)
  348.     elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem")
  349.     confirm(len(elems) == 1
  350.             and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
  351.             and elems[0].localName == "myelem"
  352.             and elems[0].prefix == "minidom"
  353.             and elems[0].tagName == "minidom:myelem"
  354.             and elems[0].nodeName == "minidom:myelem")
  355.     dom.unlink()
  356.  
  357. def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname):
  358.     nodelist = doc.getElementsByTagNameNS(nsuri, lname)
  359.     confirm(len(nodelist) == 0)
  360.  
  361. def testGetEmptyNodeListFromElementsByTagNameNS():
  362.     doc = parseString('<doc/>')
  363.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  364.         doc, 'http://xml.python.org/namespaces/a', 'localname')
  365.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  366.         doc, '*', 'splat')
  367.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  368.         doc, 'http://xml.python.org/namespaces/a', '*')
  369.  
  370.     doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
  371.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  372.         doc, "http://xml.python.org/splat", "not-there")
  373.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  374.         doc, "*", "not-there")
  375.     get_empty_nodelist_from_elements_by_tagName_ns_helper(
  376.         doc, "http://somewhere.else.net/not-there", "e")
  377.  
  378. def testElementReprAndStr():
  379.     dom = Document()
  380.     el = dom.appendChild(dom.createElement("abc"))
  381.     string1 = repr(el)
  382.     string2 = str(el)
  383.     confirm(string1 == string2)
  384.     dom.unlink()
  385.  
  386. # commented out until Fredrick's fix is checked in
  387. def _testElementReprAndStrUnicode():
  388.     dom = Document()
  389.     el = dom.appendChild(dom.createElement(u"abc"))
  390.     string1 = repr(el)
  391.     string2 = str(el)
  392.     confirm(string1 == string2)
  393.     dom.unlink()
  394.  
  395. # commented out until Fredrick's fix is checked in
  396. def _testElementReprAndStrUnicodeNS():
  397.     dom = Document()
  398.     el = dom.appendChild(
  399.         dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
  400.     string1 = repr(el)
  401.     string2 = str(el)
  402.     confirm(string1 == string2)
  403.     confirm(string1.find("slash:abc") != -1)
  404.     dom.unlink()
  405.  
  406. def testAttributeRepr():
  407.     dom = Document()
  408.     el = dom.appendChild(dom.createElement(u"abc"))
  409.     node = el.setAttribute("abc", "def")
  410.     confirm(str(node) == repr(node))
  411.     dom.unlink()
  412.  
  413. def testTextNodeRepr(): pass
  414.  
  415. def testWriteXML():
  416.     str = '<?xml version="1.0" ?><a b="c"/>'
  417.     dom = parseString(str)
  418.     domstr = dom.toxml()
  419.     dom.unlink()
  420.     confirm(str == domstr)
  421.  
  422. def testAltNewline():
  423.     str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
  424.     dom = parseString(str)
  425.     domstr = dom.toprettyxml(newl="\r\n")
  426.     dom.unlink()
  427.     confirm(domstr == str.replace("\n", "\r\n"))
  428.  
  429. def testProcessingInstruction():
  430.     dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
  431.     pi = dom.documentElement.firstChild
  432.     confirm(pi.target == "mypi"
  433.             and pi.data == "data \t\n "
  434.             and pi.nodeName == "mypi"
  435.             and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
  436.             and pi.attributes is None
  437.             and not pi.hasChildNodes()
  438.             and len(pi.childNodes) == 0
  439.             and pi.firstChild is None
  440.             and pi.lastChild is None
  441.             and pi.localName is None
  442.             and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
  443.  
  444. def testProcessingInstructionRepr(): pass
  445.  
  446. def testTextRepr(): pass
  447.  
  448. def testWriteText(): pass
  449.  
  450. def testDocumentElement(): pass
  451.  
  452. def testTooManyDocumentElements():
  453.     doc = parseString("<doc/>")
  454.     elem = doc.createElement("extra")
  455.     try:
  456.         doc.appendChild(elem)
  457.     except xml.dom.HierarchyRequestErr:
  458.         pass
  459.     else:
  460.         print "Failed to catch expected exception when" \
  461.               " adding extra document element."
  462.     elem.unlink()
  463.     doc.unlink()
  464.  
  465. def testCreateElementNS(): pass
  466.  
  467. def testCreateAttributeNS(): pass
  468.  
  469. def testParse(): pass
  470.  
  471. def testParseString(): pass
  472.  
  473. def testComment(): pass
  474.  
  475. def testAttrListItem(): pass
  476.  
  477. def testAttrListItems(): pass
  478.  
  479. def testAttrListItemNS(): pass
  480.  
  481. def testAttrListKeys(): pass
  482.  
  483. def testAttrListKeysNS(): pass
  484.  
  485. def testRemoveNamedItem():
  486.     doc = parseString("<doc a=''/>")
  487.     e = doc.documentElement
  488.     attrs = e.attributes
  489.     a1 = e.getAttributeNode("a")
  490.     a2 = attrs.removeNamedItem("a")
  491.     confirm(a1.isSameNode(a2))
  492.     try:
  493.         attrs.removeNamedItem("a")
  494.     except xml.dom.NotFoundErr:
  495.         pass
  496.  
  497. def testRemoveNamedItemNS():
  498.     doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
  499.     e = doc.documentElement
  500.     attrs = e.attributes
  501.     a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
  502.     a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
  503.     confirm(a1.isSameNode(a2))
  504.     try:
  505.         attrs.removeNamedItemNS("http://xml.python.org/", "b")
  506.     except xml.dom.NotFoundErr:
  507.         pass
  508.  
  509. def testAttrListValues(): pass
  510.  
  511. def testAttrListLength(): pass
  512.  
  513. def testAttrList__getitem__(): pass
  514.  
  515. def testAttrList__setitem__(): pass
  516.  
  517. def testSetAttrValueandNodeValue(): pass
  518.  
  519. def testParseElement(): pass
  520.  
  521. def testParseAttributes(): pass
  522.  
  523. def testParseElementNamespaces(): pass
  524.  
  525. def testParseAttributeNamespaces(): pass
  526.  
  527. def testParseProcessingInstructions(): pass
  528.  
  529. def testChildNodes(): pass
  530.  
  531. def testFirstChild(): pass
  532.  
  533. def testHasChildNodes(): pass
  534.  
  535. def testCloneElementShallow():
  536.     dom, clone = _setupCloneElement(0)
  537.     confirm(len(clone.childNodes) == 0
  538.             and clone.childNodes.length == 0
  539.             and clone.parentNode is None
  540.             and clone.toxml() == '<doc attr="value"/>'
  541.             , "testCloneElementShallow")
  542.     dom.unlink()
  543.  
  544. def testCloneElementDeep():
  545.     dom, clone = _setupCloneElement(1)
  546.     confirm(len(clone.childNodes) == 1
  547.             and clone.childNodes.length == 1
  548.             and clone.parentNode is None
  549.             and clone.toxml() == '<doc attr="value"><foo/></doc>'
  550.             , "testCloneElementDeep")
  551.     dom.unlink()
  552.  
  553. def _setupCloneElement(deep):
  554.     dom = parseString("<doc attr='value'><foo/></doc>")
  555.     root = dom.documentElement
  556.     clone = root.cloneNode(deep)
  557.     _testCloneElementCopiesAttributes(
  558.         root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
  559.     # mutilate the original so shared data is detected
  560.     root.tagName = root.nodeName = "MODIFIED"
  561.     root.setAttribute("attr", "NEW VALUE")
  562.     root.setAttribute("added", "VALUE")
  563.     return dom, clone
  564.  
  565. def _testCloneElementCopiesAttributes(e1, e2, test):
  566.     attrs1 = e1.attributes
  567.     attrs2 = e2.attributes
  568.     keys1 = attrs1.keys()
  569.     keys2 = attrs2.keys()
  570.     keys1.sort()
  571.     keys2.sort()
  572.     confirm(keys1 == keys2, "clone of element has same attribute keys")
  573.     for i in range(len(keys1)):
  574.         a1 = attrs1.item(i)
  575.         a2 = attrs2.item(i)
  576.         confirm(a1 is not a2
  577.                 and a1.value == a2.value
  578.                 and a1.nodeValue == a2.nodeValue
  579.                 and a1.namespaceURI == a2.namespaceURI
  580.                 and a1.localName == a2.localName
  581.                 , "clone of attribute node has proper attribute values")
  582.         confirm(a2.ownerElement is e2,
  583.                 "clone of attribute node correctly owned")
  584.  
  585. def testCloneDocumentShallow():
  586.     doc = parseString("<?xml version='1.0'?>\n"
  587.                       "<!-- comment -->"
  588.                       "<!DOCTYPE doc [\n"
  589.                       "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
  590.                       "]>\n"
  591.                       "<doc attr='value'/>")
  592.     doc2 = doc.cloneNode(0)
  593.     confirm(doc2 is None,
  594.             "testCloneDocumentShallow:"
  595.             " shallow cloning of documents makes no sense!")
  596.  
  597. def testCloneDocumentDeep():
  598.     doc = parseString("<?xml version='1.0'?>\n"
  599.                       "<!-- comment -->"
  600.                       "<!DOCTYPE doc [\n"
  601.                       "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
  602.                       "]>\n"
  603.                       "<doc attr='value'/>")
  604.     doc2 = doc.cloneNode(1)
  605.     confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
  606.             "testCloneDocumentDeep: document objects not distinct")
  607.     confirm(len(doc.childNodes) == len(doc2.childNodes),
  608.             "testCloneDocumentDeep: wrong number of Document children")
  609.     confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
  610.             "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
  611.     confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
  612.             "testCloneDocumentDeep: documentElement owner is not new document")
  613.     confirm(not doc.documentElement.isSameNode(doc2.documentElement),
  614.             "testCloneDocumentDeep: documentElement should not be shared")
  615.     if doc.doctype is not None:
  616.         # check the doctype iff the original DOM maintained it
  617.         confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
  618.                 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
  619.         confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
  620.         confirm(not doc.doctype.isSameNode(doc2.doctype))
  621.  
  622. def testCloneDocumentTypeDeepOk():
  623.     doctype = create_nonempty_doctype()
  624.     clone = doctype.cloneNode(1)
  625.     confirm(clone is not None
  626.             and clone.nodeName == doctype.nodeName
  627.             and clone.name == doctype.name
  628.             and clone.publicId == doctype.publicId
  629.             and clone.systemId == doctype.systemId
  630.             and len(clone.entities) == len(doctype.entities)
  631.             and clone.entities.item(len(clone.entities)) is None
  632.             and len(clone.notations) == len(doctype.notations)
  633.             and clone.notations.item(len(clone.notations)) is None
  634.             and len(clone.childNodes) == 0)
  635.     for i in range(len(doctype.entities)):
  636.         se = doctype.entities.item(i)
  637.         ce = clone.entities.item(i)
  638.         confirm((not se.isSameNode(ce))
  639.                 and (not ce.isSameNode(se))
  640.                 and ce.nodeName == se.nodeName
  641.                 and ce.notationName == se.notationName
  642.                 and ce.publicId == se.publicId
  643.                 and ce.systemId == se.systemId
  644.                 and ce.encoding == se.encoding
  645.                 and ce.actualEncoding == se.actualEncoding
  646.                 and ce.version == se.version)
  647.     for i in range(len(doctype.notations)):
  648.         sn = doctype.notations.item(i)
  649.         cn = clone.notations.item(i)
  650.         confirm((not sn.isSameNode(cn))
  651.                 and (not cn.isSameNode(sn))
  652.                 and cn.nodeName == sn.nodeName
  653.                 and cn.publicId == sn.publicId
  654.                 and cn.systemId == sn.systemId)
  655.  
  656. def testCloneDocumentTypeDeepNotOk():
  657.     doc = create_doc_with_doctype()
  658.     clone = doc.doctype.cloneNode(1)
  659.     confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
  660.  
  661. def testCloneDocumentTypeShallowOk():
  662.     doctype = create_nonempty_doctype()
  663.     clone = doctype.cloneNode(0)
  664.     confirm(clone is not None
  665.             and clone.nodeName == doctype.nodeName
  666.             and clone.name == doctype.name
  667.             and clone.publicId == doctype.publicId
  668.             and clone.systemId == doctype.systemId
  669.             and len(clone.entities) == 0
  670.             and clone.entities.item(0) is None
  671.             and len(clone.notations) == 0
  672.             and clone.notations.item(0) is None
  673.             and len(clone.childNodes) == 0)
  674.  
  675. def testCloneDocumentTypeShallowNotOk():
  676.     doc = create_doc_with_doctype()
  677.     clone = doc.doctype.cloneNode(0)
  678.     confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
  679.  
  680. def check_import_document(deep, testName):
  681.     doc1 = parseString("<doc/>")
  682.     doc2 = parseString("<doc/>")
  683.     try:
  684.         doc1.importNode(doc2, deep)
  685.     except xml.dom.NotSupportedErr:
  686.         pass
  687.     else:
  688.         raise Exception(testName +
  689.                         ": expected NotSupportedErr when importing a document")
  690.  
  691. def testImportDocumentShallow():
  692.     check_import_document(0, "testImportDocumentShallow")
  693.  
  694. def testImportDocumentDeep():
  695.     check_import_document(1, "testImportDocumentDeep")
  696.  
  697. # The tests of DocumentType importing use these helpers to construct
  698. # the documents to work with, since not all DOM builders actually
  699. # create the DocumentType nodes.
  700.  
  701. def create_doc_without_doctype(doctype=None):
  702.     return getDOMImplementation().createDocument(None, "doc", doctype)
  703.  
  704. def create_nonempty_doctype():
  705.     doctype = getDOMImplementation().createDocumentType("doc", None, None)
  706.     doctype.entities._seq = []
  707.     doctype.notations._seq = []
  708.     notation = xml.dom.minidom.Notation("my-notation", None,
  709.                                         "http://xml.python.org/notations/my")
  710.     doctype.notations._seq.append(notation)
  711.     entity = xml.dom.minidom.Entity("my-entity", None,
  712.                                     "http://xml.python.org/entities/my",
  713.                                     "my-notation")
  714.     entity.version = "1.0"
  715.     entity.encoding = "utf-8"
  716.     entity.actualEncoding = "us-ascii"
  717.     doctype.entities._seq.append(entity)
  718.     return doctype
  719.  
  720. def create_doc_with_doctype():
  721.     doctype = create_nonempty_doctype()
  722.     doc = create_doc_without_doctype(doctype)
  723.     doctype.entities.item(0).ownerDocument = doc
  724.     doctype.notations.item(0).ownerDocument = doc
  725.     return doc
  726.  
  727. def testImportDocumentTypeShallow():
  728.     src = create_doc_with_doctype()
  729.     target = create_doc_without_doctype()
  730.     try:
  731.         imported = target.importNode(src.doctype, 0)
  732.     except xml.dom.NotSupportedErr:
  733.         pass
  734.     else:
  735.         raise Exception(
  736.             "testImportDocumentTypeShallow: expected NotSupportedErr")
  737.  
  738. def testImportDocumentTypeDeep():
  739.     src = create_doc_with_doctype()
  740.     target = create_doc_without_doctype()
  741.     try:
  742.         imported = target.importNode(src.doctype, 1)
  743.     except xml.dom.NotSupportedErr:
  744.         pass
  745.     else:
  746.         raise Exception(
  747.             "testImportDocumentTypeDeep: expected NotSupportedErr")
  748.  
  749. # Testing attribute clones uses a helper, and should always be deep,
  750. # even if the argument to cloneNode is false.
  751. def check_clone_attribute(deep, testName):
  752.     doc = parseString("<doc attr='value'/>")
  753.     attr = doc.documentElement.getAttributeNode("attr")
  754.     assert attr is not None
  755.     clone = attr.cloneNode(deep)
  756.     confirm(not clone.isSameNode(attr))
  757.     confirm(not attr.isSameNode(clone))
  758.     confirm(clone.ownerElement is None,
  759.             testName + ": ownerElement should be None")
  760.     confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
  761.             testName + ": ownerDocument does not match")
  762.     confirm(clone.specified,
  763.             testName + ": cloned attribute must have specified == True")
  764.  
  765. def testCloneAttributeShallow():
  766.     check_clone_attribute(0, "testCloneAttributeShallow")
  767.  
  768. def testCloneAttributeDeep():
  769.     check_clone_attribute(1, "testCloneAttributeDeep")
  770.  
  771. def check_clone_pi(deep, testName):
  772.     doc = parseString("<?target data?><doc/>")
  773.     pi = doc.firstChild
  774.     assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
  775.     clone = pi.cloneNode(deep)
  776.     confirm(clone.target == pi.target
  777.             and clone.data == pi.data)
  778.  
  779. def testClonePIShallow():
  780.     check_clone_pi(0, "testClonePIShallow")
  781.  
  782. def testClonePIDeep():
  783.     check_clone_pi(1, "testClonePIDeep")
  784.  
  785. def testNormalize():
  786.     doc = parseString("<doc/>")
  787.     root = doc.documentElement
  788.     root.appendChild(doc.createTextNode("first"))
  789.     root.appendChild(doc.createTextNode("second"))
  790.     confirm(len(root.childNodes) == 2
  791.             and root.childNodes.length == 2, "testNormalize -- preparation")
  792.     doc.normalize()
  793.     confirm(len(root.childNodes) == 1
  794.             and root.childNodes.length == 1
  795.             and root.firstChild is root.lastChild
  796.             and root.firstChild.data == "firstsecond"
  797.             , "testNormalize -- result")
  798.     doc.unlink()
  799.  
  800.     doc = parseString("<doc/>")
  801.     root = doc.documentElement
  802.     root.appendChild(doc.createTextNode(""))
  803.     doc.normalize()
  804.     confirm(len(root.childNodes) == 0
  805.             and root.childNodes.length == 0,
  806.             "testNormalize -- single empty node removed")
  807.     doc.unlink()
  808.  
  809. def testSiblings():
  810.     doc = parseString("<doc><?pi?>text?<elm/></doc>")
  811.     root = doc.documentElement
  812.     (pi, text, elm) = root.childNodes
  813.  
  814.     confirm(pi.nextSibling is text and
  815.             pi.previousSibling is None and
  816.             text.nextSibling is elm and
  817.             text.previousSibling is pi and
  818.             elm.nextSibling is None and
  819.             elm.previousSibling is text, "testSiblings")
  820.  
  821.     doc.unlink()
  822.  
  823. def testParents():
  824.     doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
  825.     root = doc.documentElement
  826.     elm1 = root.childNodes[0]
  827.     (elm2a, elm2b) = elm1.childNodes
  828.     elm3 = elm2b.childNodes[0]
  829.  
  830.     confirm(root.parentNode is doc and
  831.             elm1.parentNode is root and
  832.             elm2a.parentNode is elm1 and
  833.             elm2b.parentNode is elm1 and
  834.             elm3.parentNode is elm2b, "testParents")
  835.  
  836.     doc.unlink()
  837.  
  838. def testNodeListItem():
  839.     doc = parseString("<doc><e/><e/></doc>")
  840.     children = doc.childNodes
  841.     docelem = children[0]
  842.     confirm(children[0] is children.item(0)
  843.             and children.item(1) is None
  844.             and docelem.childNodes.item(0) is docelem.childNodes[0]
  845.             and docelem.childNodes.item(1) is docelem.childNodes[1]
  846.             and docelem.childNodes.item(0).childNodes.item(0) is None,
  847.             "test NodeList.item()")
  848.     doc.unlink()
  849.  
  850. def testSAX2DOM():
  851.     from xml.dom import pulldom
  852.  
  853.     sax2dom = pulldom.SAX2DOM()
  854.     sax2dom.startDocument()
  855.     sax2dom.startElement("doc", {})
  856.     sax2dom.characters("text")
  857.     sax2dom.startElement("subelm", {})
  858.     sax2dom.characters("text")
  859.     sax2dom.endElement("subelm")
  860.     sax2dom.characters("text")
  861.     sax2dom.endElement("doc")
  862.     sax2dom.endDocument()
  863.  
  864.     doc = sax2dom.document
  865.     root = doc.documentElement
  866.     (text1, elm1, text2) = root.childNodes
  867.     text3 = elm1.childNodes[0]
  868.  
  869.     confirm(text1.previousSibling is None and
  870.             text1.nextSibling is elm1 and
  871.             elm1.previousSibling is text1 and
  872.             elm1.nextSibling is text2 and
  873.             text2.previousSibling is elm1 and
  874.             text2.nextSibling is None and
  875.             text3.previousSibling is None and
  876.             text3.nextSibling is None, "testSAX2DOM - siblings")
  877.  
  878.     confirm(root.parentNode is doc and
  879.             text1.parentNode is root and
  880.             elm1.parentNode is root and
  881.             text2.parentNode is root and
  882.             text3.parentNode is elm1, "testSAX2DOM - parents")
  883.  
  884.     doc.unlink()
  885.  
  886. def testEncodings():
  887.     doc = parseString('<foo>€</foo>')
  888.     confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
  889.             and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
  890.             and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
  891.             "testEncodings - encoding EURO SIGN")
  892.     doc.unlink()
  893.  
  894. class UserDataHandler:
  895.     called = 0
  896.     def handle(self, operation, key, data, src, dst):
  897.         dst.setUserData(key, data + 1, self)
  898.         src.setUserData(key, None, None)
  899.         self.called = 1
  900.  
  901. def testUserData():
  902.     dom = Document()
  903.     n = dom.createElement('e')
  904.     confirm(n.getUserData("foo") is None)
  905.     n.setUserData("foo", None, None)
  906.     confirm(n.getUserData("foo") is None)
  907.     n.setUserData("foo", 12, 12)
  908.     n.setUserData("bar", 13, 13)
  909.     confirm(n.getUserData("foo") == 12)
  910.     confirm(n.getUserData("bar") == 13)
  911.     n.setUserData("foo", None, None)
  912.     confirm(n.getUserData("foo") is None)
  913.     confirm(n.getUserData("bar") == 13)
  914.  
  915.     handler = UserDataHandler()
  916.     n.setUserData("bar", 12, handler)
  917.     c = n.cloneNode(1)
  918.     confirm(handler.called
  919.             and n.getUserData("bar") is None
  920.             and c.getUserData("bar") == 13)
  921.     n.unlink()
  922.     c.unlink()
  923.     dom.unlink()
  924.  
  925. def testRenameAttribute():
  926.     doc = parseString("<doc a='v'/>")
  927.     elem = doc.documentElement
  928.     attrmap = elem.attributes
  929.     attr = elem.attributes['a']
  930.  
  931.     # Simple renaming
  932.     attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
  933.     confirm(attr.name == "b"
  934.             and attr.nodeName == "b"
  935.             and attr.localName is None
  936.             and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
  937.             and attr.prefix is None
  938.             and attr.value == "v"
  939.             and elem.getAttributeNode("a") is None
  940.             and elem.getAttributeNode("b").isSameNode(attr)
  941.             and attrmap["b"].isSameNode(attr)
  942.             and attr.ownerDocument.isSameNode(doc)
  943.             and attr.ownerElement.isSameNode(elem))
  944.  
  945.     # Rename to have a namespace, no prefix
  946.     attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
  947.     confirm(attr.name == "c"
  948.             and attr.nodeName == "c"
  949.             and attr.localName == "c"
  950.             and attr.namespaceURI == "http://xml.python.org/ns"
  951.             and attr.prefix is None
  952.             and attr.value == "v"
  953.             and elem.getAttributeNode("a") is None
  954.             and elem.getAttributeNode("b") is None
  955.             and elem.getAttributeNode("c").isSameNode(attr)
  956.             and elem.getAttributeNodeNS(
  957.                 "http://xml.python.org/ns", "c").isSameNode(attr)
  958.             and attrmap["c"].isSameNode(attr)
  959.             and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
  960.  
  961.     # Rename to have a namespace, with prefix
  962.     attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
  963.     confirm(attr.name == "p:d"
  964.             and attr.nodeName == "p:d"
  965.             and attr.localName == "d"
  966.             and attr.namespaceURI == "http://xml.python.org/ns2"
  967.             and attr.prefix == "p"
  968.             and attr.value == "v"
  969.             and elem.getAttributeNode("a") is None
  970.             and elem.getAttributeNode("b") is None
  971.             and elem.getAttributeNode("c") is None
  972.             and elem.getAttributeNodeNS(
  973.                 "http://xml.python.org/ns", "c") is None
  974.             and elem.getAttributeNode("p:d").isSameNode(attr)
  975.             and elem.getAttributeNodeNS(
  976.                 "http://xml.python.org/ns2", "d").isSameNode(attr)
  977.             and attrmap["p:d"].isSameNode(attr)
  978.             and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
  979.  
  980.     # Rename back to a simple non-NS node
  981.     attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
  982.     confirm(attr.name == "e"
  983.             and attr.nodeName == "e"
  984.             and attr.localName is None
  985.             and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
  986.             and attr.prefix is None
  987.             and attr.value == "v"
  988.             and elem.getAttributeNode("a") is None
  989.             and elem.getAttributeNode("b") is None
  990.             and elem.getAttributeNode("c") is None
  991.             and elem.getAttributeNode("p:d") is None
  992.             and elem.getAttributeNodeNS(
  993.                 "http://xml.python.org/ns", "c") is None
  994.             and elem.getAttributeNode("e").isSameNode(attr)
  995.             and attrmap["e"].isSameNode(attr))
  996.  
  997.     try:
  998.         doc.renameNode(attr, "http://xml.python.org/ns", "xmlns")
  999.     except xml.dom.NamespaceErr:
  1000.         pass
  1001.     else:
  1002.         print "expected NamespaceErr"
  1003.  
  1004.     checkRenameNodeSharedConstraints(doc, attr)
  1005.     doc.unlink()
  1006.  
  1007. def testRenameElement():
  1008.     doc = parseString("<doc/>")
  1009.     elem = doc.documentElement
  1010.  
  1011.     # Simple renaming
  1012.     elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
  1013.     confirm(elem.tagName == "a"
  1014.             and elem.nodeName == "a"
  1015.             and elem.localName is None
  1016.             and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
  1017.             and elem.prefix is None
  1018.             and elem.ownerDocument.isSameNode(doc))
  1019.  
  1020.     # Rename to have a namespace, no prefix
  1021.     elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
  1022.     confirm(elem.tagName == "b"
  1023.             and elem.nodeName == "b"
  1024.             and elem.localName == "b"
  1025.             and elem.namespaceURI == "http://xml.python.org/ns"
  1026.             and elem.prefix is None
  1027.             and elem.ownerDocument.isSameNode(doc))
  1028.  
  1029.     # Rename to have a namespace, with prefix
  1030.     elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
  1031.     confirm(elem.tagName == "p:c"
  1032.             and elem.nodeName == "p:c"
  1033.             and elem.localName == "c"
  1034.             and elem.namespaceURI == "http://xml.python.org/ns2"
  1035.             and elem.prefix == "p"
  1036.             and elem.ownerDocument.isSameNode(doc))
  1037.  
  1038.     # Rename back to a simple non-NS node
  1039.     elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
  1040.     confirm(elem.tagName == "d"
  1041.             and elem.nodeName == "d"
  1042.             and elem.localName is None
  1043.             and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
  1044.             and elem.prefix is None
  1045.             and elem.ownerDocument.isSameNode(doc))
  1046.  
  1047.     checkRenameNodeSharedConstraints(doc, elem)
  1048.     doc.unlink()
  1049.  
  1050. def checkRenameNodeSharedConstraints(doc, node):
  1051.     # Make sure illegal NS usage is detected:
  1052.     try:
  1053.         doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo")
  1054.     except xml.dom.NamespaceErr:
  1055.         pass
  1056.     else:
  1057.         print "expected NamespaceErr"
  1058.  
  1059.     doc2 = parseString("<doc/>")
  1060.     try:
  1061.         doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
  1062.     except xml.dom.WrongDocumentErr:
  1063.         pass
  1064.     else:
  1065.         print "expected WrongDocumentErr"
  1066.  
  1067. def testRenameOther():
  1068.     # We have to create a comment node explicitly since not all DOM
  1069.     # builders used with minidom add comments to the DOM.
  1070.     doc = xml.dom.minidom.getDOMImplementation().createDocument(
  1071.         xml.dom.EMPTY_NAMESPACE, "e", None)
  1072.     node = doc.createComment("comment")
  1073.     try:
  1074.         doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
  1075.     except xml.dom.NotSupportedErr:
  1076.         pass
  1077.     else:
  1078.         print "expected NotSupportedErr when renaming comment node"
  1079.     doc.unlink()
  1080.  
  1081. def checkWholeText(node, s):
  1082.     t = node.wholeText
  1083.     confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
  1084.  
  1085. def testWholeText():
  1086.     doc = parseString("<doc>a</doc>")
  1087.     elem = doc.documentElement
  1088.     text = elem.childNodes[0]
  1089.     assert text.nodeType == Node.TEXT_NODE
  1090.  
  1091.     checkWholeText(text, "a")
  1092.     elem.appendChild(doc.createTextNode("b"))
  1093.     checkWholeText(text, "ab")
  1094.     elem.insertBefore(doc.createCDATASection("c"), text)
  1095.     checkWholeText(text, "cab")
  1096.  
  1097.     # make sure we don't cross other nodes
  1098.     splitter = doc.createComment("comment")
  1099.     elem.appendChild(splitter)
  1100.     text2 = doc.createTextNode("d")
  1101.     elem.appendChild(text2)
  1102.     checkWholeText(text, "cab")
  1103.     checkWholeText(text2, "d")
  1104.  
  1105.     x = doc.createElement("x")
  1106.     elem.replaceChild(x, splitter)
  1107.     splitter = x
  1108.     checkWholeText(text, "cab")
  1109.     checkWholeText(text2, "d")
  1110.  
  1111.     x = doc.createProcessingInstruction("y", "z")
  1112.     elem.replaceChild(x, splitter)
  1113.     splitter = x
  1114.     checkWholeText(text, "cab")
  1115.     checkWholeText(text2, "d")
  1116.  
  1117.     elem.removeChild(splitter)
  1118.     checkWholeText(text, "cabd")
  1119.     checkWholeText(text2, "cabd")
  1120.  
  1121. def testReplaceWholeText():
  1122.     def setup():
  1123.         doc = parseString("<doc>a<e/>d</doc>")
  1124.         elem = doc.documentElement
  1125.         text1 = elem.firstChild
  1126.         text2 = elem.lastChild
  1127.         splitter = text1.nextSibling
  1128.         elem.insertBefore(doc.createTextNode("b"), splitter)
  1129.         elem.insertBefore(doc.createCDATASection("c"), text1)
  1130.         return doc, elem, text1, splitter, text2
  1131.  
  1132.     doc, elem, text1, splitter, text2 = setup()
  1133.     text = text1.replaceWholeText("new content")
  1134.     checkWholeText(text, "new content")
  1135.     checkWholeText(text2, "d")
  1136.     confirm(len(elem.childNodes) == 3)
  1137.  
  1138.     doc, elem, text1, splitter, text2 = setup()
  1139.     text = text2.replaceWholeText("new content")
  1140.     checkWholeText(text, "new content")
  1141.     checkWholeText(text1, "cab")
  1142.     confirm(len(elem.childNodes) == 5)
  1143.  
  1144.     doc, elem, text1, splitter, text2 = setup()
  1145.     text = text1.replaceWholeText("")
  1146.     checkWholeText(text2, "d")
  1147.     confirm(text is None
  1148.             and len(elem.childNodes) == 2)
  1149.  
  1150. def testSchemaType():
  1151.     doc = parseString(
  1152.         "<!DOCTYPE doc [\n"
  1153.         "  <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
  1154.         "  <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
  1155.         "  <!ATTLIST doc id   ID       #IMPLIED \n"
  1156.         "                ref  IDREF    #IMPLIED \n"
  1157.         "                refs IDREFS   #IMPLIED \n"
  1158.         "                enum (a|b)    #IMPLIED \n"
  1159.         "                ent  ENTITY   #IMPLIED \n"
  1160.         "                ents ENTITIES #IMPLIED \n"
  1161.         "                nm   NMTOKEN  #IMPLIED \n"
  1162.         "                nms  NMTOKENS #IMPLIED \n"
  1163.         "                text CDATA    #IMPLIED \n"
  1164.         "    >\n"
  1165.         "]><doc id='name' notid='name' text='splat!' enum='b'"
  1166.         "       ref='name' refs='name name' ent='e1' ents='e1 e2'"
  1167.         "       nm='123' nms='123 abc' />")
  1168.     elem = doc.documentElement
  1169.     # We don't want to rely on any specific loader at this point, so
  1170.     # just make sure we can get to all the names, and that the
  1171.     # DTD-based namespace is right.  The names can vary by loader
  1172.     # since each supports a different level of DTD information.
  1173.     t = elem.schemaType
  1174.     confirm(t.name is None
  1175.             and t.namespace == xml.dom.EMPTY_NAMESPACE)
  1176.     names = "id notid text enum ref refs ent ents nm nms".split()
  1177.     for name in names:
  1178.         a = elem.getAttributeNode(name)
  1179.         t = a.schemaType
  1180.         confirm(hasattr(t, "name")
  1181.                 and t.namespace == xml.dom.EMPTY_NAMESPACE)
  1182.  
  1183. def testSetIdAttribute():
  1184.     doc = parseString("<doc a1='v' a2='w'/>")
  1185.     e = doc.documentElement
  1186.     a1 = e.getAttributeNode("a1")
  1187.     a2 = e.getAttributeNode("a2")
  1188.     confirm(doc.getElementById("v") is None
  1189.             and not a1.isId
  1190.             and not a2.isId)
  1191.     e.setIdAttribute("a1")
  1192.     confirm(e.isSameNode(doc.getElementById("v"))
  1193.             and a1.isId
  1194.             and not a2.isId)
  1195.     e.setIdAttribute("a2")
  1196.     confirm(e.isSameNode(doc.getElementById("v"))
  1197.             and e.isSameNode(doc.getElementById("w"))
  1198.             and a1.isId
  1199.             and a2.isId)
  1200.     # replace the a1 node; the new node should *not* be an ID
  1201.     a3 = doc.createAttribute("a1")
  1202.     a3.value = "v"
  1203.     e.setAttributeNode(a3)
  1204.     confirm(doc.getElementById("v") is None
  1205.             and e.isSameNode(doc.getElementById("w"))
  1206.             and not a1.isId
  1207.             and a2.isId
  1208.             and not a3.isId)
  1209.     # renaming an attribute should not affect its ID-ness:
  1210.     doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
  1211.     confirm(e.isSameNode(doc.getElementById("w"))
  1212.             and a2.isId)
  1213.  
  1214. def testSetIdAttributeNS():
  1215.     NS1 = "http://xml.python.org/ns1"
  1216.     NS2 = "http://xml.python.org/ns2"
  1217.     doc = parseString("<doc"
  1218.                       " xmlns:ns1='" + NS1 + "'"
  1219.                       " xmlns:ns2='" + NS2 + "'"
  1220.                       " ns1:a1='v' ns2:a2='w'/>")
  1221.     e = doc.documentElement
  1222.     a1 = e.getAttributeNodeNS(NS1, "a1")
  1223.     a2 = e.getAttributeNodeNS(NS2, "a2")
  1224.     confirm(doc.getElementById("v") is None
  1225.             and not a1.isId
  1226.             and not a2.isId)
  1227.     e.setIdAttributeNS(NS1, "a1")
  1228.     confirm(e.isSameNode(doc.getElementById("v"))
  1229.             and a1.isId
  1230.             and not a2.isId)
  1231.     e.setIdAttributeNS(NS2, "a2")
  1232.     confirm(e.isSameNode(doc.getElementById("v"))
  1233.             and e.isSameNode(doc.getElementById("w"))
  1234.             and a1.isId
  1235.             and a2.isId)
  1236.     # replace the a1 node; the new node should *not* be an ID
  1237.     a3 = doc.createAttributeNS(NS1, "a1")
  1238.     a3.value = "v"
  1239.     e.setAttributeNode(a3)
  1240.     confirm(e.isSameNode(doc.getElementById("w")))
  1241.     confirm(not a1.isId)
  1242.     confirm(a2.isId)
  1243.     confirm(not a3.isId)
  1244.     confirm(doc.getElementById("v") is None)
  1245.     # renaming an attribute should not affect its ID-ness:
  1246.     doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
  1247.     confirm(e.isSameNode(doc.getElementById("w"))
  1248.             and a2.isId)
  1249.  
  1250. def testSetIdAttributeNode():
  1251.     NS1 = "http://xml.python.org/ns1"
  1252.     NS2 = "http://xml.python.org/ns2"
  1253.     doc = parseString("<doc"
  1254.                       " xmlns:ns1='" + NS1 + "'"
  1255.                       " xmlns:ns2='" + NS2 + "'"
  1256.                       " ns1:a1='v' ns2:a2='w'/>")
  1257.     e = doc.documentElement
  1258.     a1 = e.getAttributeNodeNS(NS1, "a1")
  1259.     a2 = e.getAttributeNodeNS(NS2, "a2")
  1260.     confirm(doc.getElementById("v") is None
  1261.             and not a1.isId
  1262.             and not a2.isId)
  1263.     e.setIdAttributeNode(a1)
  1264.     confirm(e.isSameNode(doc.getElementById("v"))
  1265.             and a1.isId
  1266.             and not a2.isId)
  1267.     e.setIdAttributeNode(a2)
  1268.     confirm(e.isSameNode(doc.getElementById("v"))
  1269.             and e.isSameNode(doc.getElementById("w"))
  1270.             and a1.isId
  1271.             and a2.isId)
  1272.     # replace the a1 node; the new node should *not* be an ID
  1273.     a3 = doc.createAttributeNS(NS1, "a1")
  1274.     a3.value = "v"
  1275.     e.setAttributeNode(a3)
  1276.     confirm(e.isSameNode(doc.getElementById("w")))
  1277.     confirm(not a1.isId)
  1278.     confirm(a2.isId)
  1279.     confirm(not a3.isId)
  1280.     confirm(doc.getElementById("v") is None)
  1281.     # renaming an attribute should not affect its ID-ness:
  1282.     doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
  1283.     confirm(e.isSameNode(doc.getElementById("w"))
  1284.             and a2.isId)
  1285.  
  1286. def testPickledDocument():
  1287.     doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
  1288.                       "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
  1289.                       " 'http://xml.python.org/system' [\n"
  1290.                       "  <!ELEMENT e EMPTY>\n"
  1291.                       "  <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
  1292.                       "]><doc attr='value'> text\n"
  1293.                       "<?pi sample?> <!-- comment --> <e/> </doc>")
  1294.     s = pickle.dumps(doc)
  1295.     doc2 = pickle.loads(s)
  1296.     stack = [(doc, doc2)]
  1297.     while stack:
  1298.         n1, n2 = stack.pop()
  1299.         confirm(n1.nodeType == n2.nodeType
  1300.                 and len(n1.childNodes) == len(n2.childNodes)
  1301.                 and n1.nodeName == n2.nodeName
  1302.                 and not n1.isSameNode(n2)
  1303.                 and not n2.isSameNode(n1))
  1304.         if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
  1305.             len(n1.entities)
  1306.             len(n2.entities)
  1307.             len(n1.notations)
  1308.             len(n2.notations)
  1309.             confirm(len(n1.entities) == len(n2.entities)
  1310.                     and len(n1.notations) == len(n2.notations))
  1311.             for i in range(len(n1.notations)):
  1312.                 no1 = n1.notations.item(i)
  1313.                 no2 = n1.notations.item(i)
  1314.                 confirm(no1.name == no2.name
  1315.                         and no1.publicId == no2.publicId
  1316.                         and no1.systemId == no2.systemId)
  1317.                 statck.append((no1, no2))
  1318.             for i in range(len(n1.entities)):
  1319.                 e1 = n1.entities.item(i)
  1320.                 e2 = n2.entities.item(i)
  1321.                 confirm(e1.notationName == e2.notationName
  1322.                         and e1.publicId == e2.publicId
  1323.                         and e1.systemId == e2.systemId)
  1324.                 stack.append((e1, e2))
  1325.         if n1.nodeType != Node.DOCUMENT_NODE:
  1326.             confirm(n1.ownerDocument.isSameNode(doc)
  1327.                     and n2.ownerDocument.isSameNode(doc2))
  1328.         for i in range(len(n1.childNodes)):
  1329.             stack.append((n1.childNodes[i], n2.childNodes[i]))
  1330.  
  1331.  
  1332. # --- MAIN PROGRAM
  1333.  
  1334. names = globals().keys()
  1335. names.sort()
  1336.  
  1337. failed = []
  1338.  
  1339. try:
  1340.     Node.allnodes
  1341. except AttributeError:
  1342.     # We don't actually have the minidom from the standard library,
  1343.     # but are picking up the PyXML version from site-packages.
  1344.     def check_allnodes():
  1345.         pass
  1346. else:
  1347.     def check_allnodes():
  1348.         confirm(len(Node.allnodes) == 0,
  1349.                 "assertion: len(Node.allnodes) == 0")
  1350.         if len(Node.allnodes):
  1351.             print "Garbage left over:"
  1352.             if verbose:
  1353.                 print Node.allnodes.items()[0:10]
  1354.             else:
  1355.                 # Don't print specific nodes if repeatable results
  1356.                 # are needed
  1357.                 print len(Node.allnodes)
  1358.         Node.allnodes = {}
  1359.  
  1360. for name in names:
  1361.     if name.startswith("test"):
  1362.         func = globals()[name]
  1363.         try:
  1364.             func()
  1365.             check_allnodes()
  1366.         except:
  1367.             failed.append(name)
  1368.             print "Test Failed: ", name
  1369.             sys.stdout.flush()
  1370.             traceback.print_exception(*sys.exc_info())
  1371.             print repr(sys.exc_info()[1])
  1372.             Node.allnodes = {}
  1373.  
  1374. if failed:
  1375.     print "\n\n\n**** Check for failures in these tests:"
  1376.     for name in failed:
  1377.         print "  " + name
  1378.